<?php
/*
 * author: Mykolas
 * Istorinių duomenų importavimas iš xls failo ir išsaugojimas duomenų bazėje
 * 
 * Ar reikia patikrinti ar paraiškų kodai jau duombazėje? ir ką daryti neradus?
 *      Dabar tikrinama. Neradus vartotojas perspėjamas, eilutė praleidžiama (į db nerašoma)
 * Ar reikia tikrinti kad nebūtų duomenų ateičiai? 
 *      Dabar tokie duomenys praleidžiami, vartotojas apie tai įspėjamas
 *      TODO: serverio laikas  vs vartotojo laikas vs GMT vs periodai
 * Ar priemonių kodai laikomi vienodais jei skiriasi raidžių case?
 *      Dabar laikomi vienodais
 * Ką daryti jei duomenys tik gautų arba tik suadministruotų paraiškų
 *      Dabar tik perspėjamas naudotojas, įrašoma į db, nežinoma reikšmė pažymima -1
 *      Jei nėra bent vienos iš kortelių - duomenys neanalizuojami
 * Jei aprašyta kelios eilutės tai pačiai priemonei ir datai - ar perspėti
 *      Dabar netikrinama - neperspėjama
 * 
 * Failo tipo tikrinimas pašalintas. Išbandyta ir veikia su 2003 MS office xml ir xls formatais
 * Nusiuntus netinkamą failą pvz paveiksliuką - meta klaidą kad nerandama kortelė.
*/

$application_quantities = Array();

require_once 'PhpExcel/PHPExcel/IOFactory.php';

function parse_data_file($inputFileName){
    global $historical;
    
    if(!file_exists($inputFileName)){
        if($historical){
            throw new Exception("Nerastas nurodytas istorinių duomenų failas");
        }
        throw new Exception("Nerastas nurodytas prognozuojamų kiekių failas");
    }
    $objPHPExcel = PHPExcel_IOFactory::load($inputFileName);
    
    if(($received_sheet = $objPHPExcel->getSheetByName('Gautos')) == null){
        throw new Exception('Nurodytame faile nerasta kortelė "Gautos"');
    }
    if(($administrated_sheet = $objPHPExcel->getSheetByName('Suadministruotos')) == null && $historical){
        throw new Exception('Nurodytame faile nerasta kortelė "Suadministruotos"');
    }
    
    parse_applications($received_sheet, "received");
    if($historical){
        parse_applications($administrated_sheet, "administrated");
    }

    global $application_quantities;
    if(empty($application_quantities)){
        add_warning("Į duomenų bazę neįrašyta nė viena eilutė");
        return;
    }
    save_quantities_to_db();
    if($historical){
        add_success("Istoriniai duomenys sėkmingai įrašyti");
    }
    else{
        add_success("Kiekių prognozė sėkmingai įrašyta");
    }
}

//TODO: remiamasi absoliučiom koordinatėm pradiniam taškui rasti. Gal galima geriau?
function parse_applications(PHPExcel_Worksheet $sheet, $type){
    global $application_quantities;
    global $historical;
    
    //Susirenkame visų DB esančių priemonių kodus
    $support_mesure_codes = Array();
    $result = mysql_query('SELECT code FROM support');
    while($code = mysql_fetch_array($result, MYSQLI_NUM)){
        array_push($support_mesure_codes, strtoupper($code[0]));
    }
    
    //Susirenkame visas datas
    $dates = Array();
    $ignored_dates = Array();
    for($column = 1; ($date = $sheet->getCellByColumnAndRow($column, 1)->getValue()) != ''; $column++){
        $date = PHPExcel_Style_NumberFormat::toFormattedString($date, "yyyy-mm-dd");
        array_push($dates, $date);
        //TODO: serverio laikas  vs vartotojo laikas vs GMT vs periodai
        if(strtotime($date) > time() && $historical){
            array_push($ignored_dates, $date);
            add_warning('Importuojant istorinius paraiškų kiekius rasta data ateityje: "'.$date.'" (Kortelė: "'.$sheet->getTitle().'", stulpelis: '.($column+1).'). Visi paraiškų kiekiai šiam laikotarpiui bus praleisti.');
        }
        if(strtotime($date) < time() && !$historical){
            array_push($ignored_dates, $date);
            add_warning('Importuojant prognozuojamus paraiškų kiekius rasta data praeityje: "'.$date.'" (Kortelė: "'.$sheet->getTitle().'", stulpelis: '.($column+1).'). Visi paraiškų kiekiai šiam laikotarpiui bus praleisti.');
        }
    }
    
    //Patikriname ar datos išrikiuotos
    for($i = 0; $i < (count($dates) - 1 ); $i++){
        if(strtotime($dates[$i]) >= strtotime($dates[$i+1])){
            throw new Exception('Klaida istorinių duomenų faile: periodas prasideda vėliau nei baigiasi ('.($i+2).' ir '.($i+3).'  stulpeliai kortelėje "'.$sheet->getTitle().'")');
        }
    }
    
    
    for($row = 2; ($measure_code = $sheet->getCellByColumnAndRow(0, $row)->getValue()) != ''; $row++){
        if(!in_array(strtoupper($measure_code), $support_mesure_codes)){
            add_warning('Paramos priemonė "'.$measure_code.'" dar neaprašyta. Eilutė praleista. (Kortelė: "'.$sheet->getTitle().'", eilutė: '.$row.'))');
            continue;
        }
        for($column = 1; $column < count($dates); $column++){
            if(in_array($dates[$column], $ignored_dates)){
                continue;
            }
            $cell_value = $sheet->getCellByColumnAndRow($column, $row)->getValue();
            $accumulated_cell_value = 0; //Kiek paraiškų periode jau paskirstyta
            $days_in_period = (strtotime($dates[$column]) - strtotime($dates[$column-1])) / 86400;
            for($d = 1; $d <= $days_in_period; $d++){
                $day_value = round(($cell_value - $accumulated_cell_value) / ($days_in_period - ($d - 1)));
                if($d == $days_in_period){ //Paskutinei dienai periode - viskas kas liko
                    $day_value = $cell_value - $accumulated_cell_value;
                }
                $accumulated_cell_value += $day_value;
                
                $current_date = date("Y-m-d", strtotime($dates[$column - 1]) + ($d - 1) * 86400);
                
                if($type == "received"){
                    //TODO: Patikrinti ar tokios nėra dar
                    array_push($application_quantities, Array(
                        'date' => $current_date,
                        'measure_code' => $measure_code,
                        'received' => $day_value,
                        'administrated' => -1
                    ));
                }
                elseif($type == "administrated"){
                    $match_found = false;
                    for($i = 0; $i < count($application_quantities); $i++){
                        if($application_quantities[$i]['date'] == $current_date 
                                && $application_quantities[$i]['measure_code'] == $measure_code){
                            $match_found = true;
                            break;
                        }
                    }
                    if($match_found){
                        $application_quantities[$i]['administrated'] = $day_value;
                    }
                    else {
                        add_warning('Nerasta duomenų apie priemonės "'.$measure_code.'" gautų paraiškų skaičių (bet rastas apdorotų paraiškų skaičius). Gautų paraiškų skaičius duomenų bazėje bus pažymėtas kaip nežinoma reikšmė.');
                        array_push($application_quantities, Array(
                            'date' => $current_date,
                            'measure_code' => $measure_code,
                            'received' => -1,
                            'administrated' => $day_value
                        ));
                    }
                }
            }
        }
    }    
}

function save_quantities_to_db(){
    global $application_quantities;
    global $warning_messages;
    global $historical;
       
    foreach($application_quantities as $record){
        if($record['administrated'] == -1 && $historical){
            array_push($warning_messages, 'Nerasta duomenų apie priemonės "'.$measure_code.'" apdorotų paraiškų skaičių (bet rastas gautų paraiškų skaičius). Apdorotų paraiškų skaičius duomenų bazėje bus pažymėtas kaip nežinoma reikšmė.');
        }
        if($historical){
            $sql_query = sprintf(
                    "INSERT INTO historical_quantities (date, measure_code, received, administrated) VALUES ('%s', '%s', %d, %d) 
                    ON DUPLICATE KEY UPDATE received=%d, administrated=%d",
                mysql_real_escape_string($record['date']),
                mysql_real_escape_string($record['measure_code']),
                mysql_real_escape_string($record['received']),
                mysql_real_escape_string($record['administrated']),
                mysql_real_escape_string($record['received']),
                mysql_real_escape_string($record['administrated'])
            );
        }
        else{
            $sql_query = sprintf(
                    "INSERT INTO forecast_quantities (date, measure_code, received) VALUES ('%s', '%s', %d) 
                    ON DUPLICATE KEY UPDATE received=%d",
                mysql_real_escape_string($record['date']),
                mysql_real_escape_string($record['measure_code']),
                mysql_real_escape_string($record['received']),
                mysql_real_escape_string($record['received'])
            );
        }
        if(($result = mysql_query($sql_query)) === false){
            if($historical){
                throw new Exception('Klaida įrašant istorinius paraiškų kiekius į duomenų bazę: '.mysql_error());
            }
            else{
                throw new Exception('Klaida įrašant paraiškų kiekių prognozes į duomenų bazę: '.mysql_error());
            }
        }
    }
}

if(isset($_POST['real_action_script']) && $_POST['real_action_script'] == 'ApplicationQuantitiesImport.php'){
    unset($_POST['real_action_script']);
    if(!isset($_POST['dataType']) || ($_POST['dataType'] != 'historicalQuantities' && $_POST['dataType'] != 'forecastQuantities')){
        echo $_POST['dataType'];
        return;
    }
    if($_POST['dataType'] == 'historicalQuantities'){
        $historical = true;
    }
    if($_POST['dataType'] == 'forecastQuantities'){
        $historical = false;
    }
    
    if(isset($_FILES['dataFile'])){
        try{
            parse_data_file($_FILES['dataFile']['tmp_name']);
        }
        catch (Exception $e){
            add_error($e->getMessage());
        }
    }
}
?>